package cn.spream.jstudy.reflect;

import java.lang.reflect.*;

/**
 * java反射
 * Created by IntelliJ IDEA.
 * User: cn.spream
 * Date: 12-8-10
 * Time: 下午4:56
 * To change this template use File | Settings | File Templates.
 */
public class ReflectHandle {

    /**
     * 获得对象的类路径
     * @return
     */
    public String getClassPath(){
        Person1 xiaoming = new Person1();
        Class<Person1> clazz = (Class<Person1>) xiaoming.getClass();
        String classPath = clazz.getName();
        return classPath;
    }

    /**
     * 根据classPath实例化Class
     * @param classPath
     * @return
     */
    public Class<?> instanceClass(String classPath){
        Class<?> clazz = null;
        try {
            clazz = Class.forName(classPath);
        } catch (ClassNotFoundException e) {
            e.printStackTrace();  //To change body of catch statement use File | Settings | File Templates.
        }
        return clazz;
    }

    /**
     * 根据class生成对象
     * @param classPerson
     * @return
     */
    public Person1 classToPerson(Class<Person1> classPerson){
        Person1 person = null;
        try {
            person = classPerson.newInstance();
        } catch (InstantiationException e) {
            e.printStackTrace();  //To change body of catch statement use File | Settings | File Templates.
        } catch (IllegalAccessException e) {
            e.printStackTrace();  //To change body of catch statement use File | Settings | File Templates.
        }
        return person;
    }

    /**
     * 通过Class调用构造函数
     */
    public void classCallConstructor(){
        Class<Person1> clazz = (Class<Person1>) instanceClass(getClassPath());
        Constructor<Person1>[] constructors = (Constructor<Person1>[]) clazz.getConstructors();
        Person1 person0 = null;
        Person1 person1 = null;
        Person1 person2 = null;
        Person1 person3 = null;
        try {
            person0 = constructors[0].newInstance("xiaoming");
            person1 = constructors[1].newInstance(22);
            person2 = constructors[2].newInstance("xiaoming", 22);
            person3 = constructors[3].newInstance();
        } catch (InstantiationException e) {
            e.printStackTrace();  //To change body of catch statement use File | Settings | File Templates.
        } catch (IllegalAccessException e) {
            e.printStackTrace();  //To change body of catch statement use File | Settings | File Templates.
        } catch (InvocationTargetException e) {
            e.printStackTrace();  //To change body of catch statement use File | Settings | File Templates.
        }
        System.out.println(person0);
        System.out.println(person1);
        System.out.println(person2);
        System.out.println(person3);
    }

    /**
     * 获取接口的名字
     */
    public void interfaceName(){
        try {
            Class<?> clazz = Class.forName("cn.spream.jstudy.reflect.Person2");
            Class<?>[] interfaces = clazz.getInterfaces();
            for (Class inter : interfaces){
                System.out.println(inter.getName());
            }
        } catch (ClassNotFoundException e) {
            e.printStackTrace();  //To change body of catch statement use File | Settings | File Templates.
        }
    }

    /**
     * 获取超类的名称
     */
    public void superClassName(){
        try {
            Class<?> clazz = Class.forName("cn.spream.jstudy.reflect.Person2");
            Class<?> superClass = clazz.getSuperclass();
            System.out.println(superClass.getName());
        } catch (ClassNotFoundException e) {
            e.printStackTrace();  //To change body of catch statement use File | Settings | File Templates.
        }
    }

    /**
     * 获取类的构造方法
     */
    public void constructorName(){
        try {
            Class<?> clazz = Class.forName("cn.spream.jstudy.reflect.Person2");
            Constructor<?>[] constructors = clazz.getConstructors();
            for (Constructor constructor : constructors){
                System.out.println(constructor);
            }
        } catch (ClassNotFoundException e) {
            e.printStackTrace();  //To change body of catch statement use File | Settings | File Templates.
        }
    }

    /**
     * 获取类构造方法信息
     */
    public void constructorInfo(){
        try {
            Class<?> clazz = Class.forName("cn.spream.jstudy.reflect.Person2");
            Constructor<?>[] constructors = clazz.getConstructors();
            for (Constructor constructor : constructors){
                String modifier = Modifier.toString(constructor.getModifiers());
                String constructorName = constructor.getName();
                Class<?>[] parameterTypes = constructor.getParameterTypes();
                System.out.print(modifier + " " + constructorName + " (");
                for(int i = 0; i < parameterTypes.length; i++){
                    System.out.print(parameterTypes[i].getName() + " arg" + i);
                    if(i < parameterTypes.length - 1){
                        System.out.print(",");
                    }
                }
                System.out.println(")");
            }
        } catch (ClassNotFoundException e) {
            e.printStackTrace();  //To change body of catch statement use File | Settings | File Templates.
        }
    }

    /**
     * 获得方法信息
     */
    public void methodInfo(){
        try {
            Class<?> clazz = Class.forName("cn.spream.jstudy.reflect.Person2");
            Method[] methods = clazz.getMethods();
            for(Method method : methods){
                String modifier = Modifier.toString(method.getModifiers());
                String returnType = method.getReturnType().getName();
                String methodName = method.getName();
                Class<?>[] parameterTypes = method.getParameterTypes();
                Class<?>[] exceptions = method.getExceptionTypes();
                System.out.print(modifier + " " + returnType + " " + methodName + "(");
                for(int i = 0; i < parameterTypes.length; i++){
                    System.out.print(parameterTypes[i].getName() + " arg" + i);
                    if(i < parameterTypes.length - 1){
                        System.out.print(",");
                    }
                }
                System.out.print(")");
                if(exceptions.length > 0){
                    System.out.print(" throws ");
                    for(int j = 0; j < exceptions.length; j ++){
                        System.out.print(exceptions[j].getName());
                        if(j < exceptions.length - 1){
                            System.out.print(",");
                        }
                    }
                }
                System.out.println("");
            }
        } catch (ClassNotFoundException e) {
            e.printStackTrace();  //To change body of catch statement use File | Settings | File Templates.
        }
    }

    /**
     * 获得属性信息
     */
    public void fieldInfo(){
        try {
            Class<?> clazz = Class.forName("cn.spream.jstudy.reflect.Person2");

            System.out.println("========本类中的属性=======");
            Field[] declaredFields = clazz.getDeclaredFields();
            for(Field field : declaredFields){
                String modifier = Modifier.toString(field.getModifiers());
                String type = field.getType().getName();
                String name = field.getName();
                System.out.println(modifier + " " + type + " " + name);
            }

            System.out.println("========接口或父类中的属性=======");
            Field[] fields = clazz.getFields();
            for(Field field : fields){
                String modifier = Modifier.toString(field.getModifiers());
                String type = field.getType().getName();
                String name = field.getName();
                System.out.println(modifier + " " + type + " " + name);
            }
        } catch (ClassNotFoundException e) {
            e.printStackTrace();  //To change body of catch statement use File | Settings | File Templates.
        }
    }

    /**
     * 调用方法
     */
    public void callMethod(){
        try {
            Class<?> clazz = Class.forName("cn.spream.jstudy.reflect.Person2");
            //调用无参数的方法
            Method method = clazz.getMethod("sayChina");
            method.invoke(clazz.newInstance());

            //调用有参数的方法
            Method method1 = clazz.getMethod("sayHello", String.class, int.class);
            method1.invoke(clazz.newInstance(), "xiaoming", 22);
        } catch (ClassNotFoundException e) {
            e.printStackTrace();  //To change body of catch statement use File | Settings | File Templates.
        } catch (NoSuchMethodException e) {
            e.printStackTrace();  //To change body of catch statement use File | Settings | File Templates.
        } catch (InvocationTargetException e) {
            e.printStackTrace();  //To change body of catch statement use File | Settings | File Templates.
        } catch (IllegalAccessException e) {
            e.printStackTrace();  //To change body of catch statement use File | Settings | File Templates.
        } catch (InstantiationException e) {
            e.printStackTrace();  //To change body of catch statement use File | Settings | File Templates.
        }
    }

    /**
     * 属性操作
     */
    public void fieldHandle(){
        try {
            Class<?> clazz = Class.forName("cn.spream.jstudy.reflect.Person2");
            Object obj = clazz.newInstance();
            Field field = clazz.getDeclaredField("name");
            field.setAccessible(true);
            field.set(obj, "xiaohong");
            System.out.println(field.get(obj));
        } catch (ClassNotFoundException e) {
            e.printStackTrace();  //To change body of catch statement use File | Settings | File Templates.
        } catch (NoSuchFieldException e) {
            e.printStackTrace();  //To change body of catch statement use File | Settings | File Templates.
        } catch (InstantiationException e) {
            e.printStackTrace();  //To change body of catch statement use File | Settings | File Templates.
        } catch (IllegalAccessException e) {
            e.printStackTrace();  //To change body of catch statement use File | Settings | File Templates.
        }
    }

    /**
     * 处理数组
     */
    public void arrayHandle(){
        int data[] = {0, 1, 2, 3, 4, 5};
        Class<?> clazz = data.getClass().getComponentType();
        System.out.println("数组类型：" + clazz.getName());
        System.out.println("数组长度：" + Array.getLength(data));
        System.out.println("第一个元素：" + Array.get(data, 0));
        Array.set(data, 0, 100);
        System.out.println("修改后第一个元素：" + Array.get(data, 0));
    }

    /**
     * 修改数组
     */
    public void modifyArray(){
        int data[] = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9};
        Class<?> clazz = data.getClass().getComponentType();
        Object newArray = Array.newInstance(clazz, 15);
        System.arraycopy(data, 0, newArray, 0, data.length);
        int arrays[] = (int[]) newArray;
        for(int i = 0; i < Array.getLength(arrays); i++){
            System.out.print(Array.get(arrays, i) + " ");
        }
    }

    /**
     * 类加载器
     */
    public void classLoader(){
        System.out.println(new Person1().getClass().getClassLoader().getClass().getName());
    }

    public static void main(String[] args) {
        ReflectHandle reflectHandle = new ReflectHandle();

//        String classPath = reflectHandle.getClassPath();
//        System.out.println("classPath:" + classPath);

//        Class<Person1> personClass = (Class<Person1>) reflectHandle.instanceClass(classPath);
//        System.out.println("classPath:" + personClass.getName());

//        Person1 person = reflectHandle.classToPerson(personClass);
//        person.setName("xiaoming");
//        person.setAge(21);
//        System.out.println("person:" + person);

//        reflectHandle.classCallConstructor();

//        reflectHandle.superClassName();

//        reflectHandle.interfaceName();

//        reflectHandle.constructorName();

//        reflectHandle.constructorInfo();

//        reflectHandle.methodInfo();

//        reflectHandle.fieldInfo();

//        reflectHandle.callMethod();

//        reflectHandle.fieldHandle();

//        reflectHandle.arrayHandle();

//        reflectHandle.modifyArray();

        reflectHandle.classLoader();
    }

}
